package service

import (
	"buding-ai/internal/core"
	"buding-ai/internal/repository"
	"buding-ai/internal/repository/model"
	"buding-ai/internal/web/dto"
	"buding-ai/pkg/mcpTool"
	"buding-ai/pkg/utils/paginate"
	"errors"
	"fmt"
	"strings"
	"sync"
	"time"
)

var (
	ErrMcpExists     = errors.New("mcp already exists")
	ErrMcpNotFound   = errors.New("mcp not found")
	ErrMcpConnection = errors.New("failed to connect to mcp")
)

// 缓存key前缀
const mcpCachePrefix = "mcp:"

// McpService MCP服务
type McpService struct {
	mcpRepository *repository.McpRepository
}

var (
	mcpSrv  *McpService
	mcpOnce sync.Once
)

// NewMcpService 创建MCP服务实例
func NewMcpService() *McpService {
	mcpOnce.Do(func() {
		mcpSrv = &McpService{
			mcpRepository: repository.GetMcpRepository(),
		}
	})
	return mcpSrv
}

// Create 创建MCP
func (srv *McpService) Create(mcpDTO dto.McpDTO) (*model.Mcp, error) {
	// 检查名称是否已存在
	var existMcp model.Mcp
	if core.DB.Where("name = ?", mcpDTO.Name).First(&existMcp).RowsAffected > 0 {
		return nil, ErrMcpExists
	}

	// 测试连接
	if err := mcpTool.Ping(mcpDTO.Cmd, strings.Split(mcpDTO.Env, ","), strings.Split(mcpDTO.Params, ","), mcpDTO.Type); err != nil {
		return nil, ErrMcpConnection
	}

	// 创建MCP
	mcp := model.Mcp{
		Name:     mcpDTO.Name,
		Describe: mcpDTO.Describe,
		Type:     mcpDTO.Type,
		Status:   mcpDTO.Status,
		Cmd:      mcpDTO.Cmd,
		Params:   mcpDTO.Params,
		Env:      mcpDTO.Env,
	}

	// 开启事务
	tx := core.DB.Begin()
	if err := tx.Create(&mcp).Error; err != nil {
		tx.Rollback()
		return nil, err
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return nil, err
	}

	return &mcp, nil
}

// Delete 删除MCP
func (srv *McpService) Delete(id uint64) error {
	// 开启事务
	tx := core.DB.Begin()

	var mcp model.Mcp
	if err := tx.First(&mcp, id).Error; err != nil {
		tx.Rollback()
		return ErrMcpNotFound
	}

	// 软删除MCP
	if err := tx.Delete(&mcp).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return err
	}

	// 从缓存删除
	cacheKey := fmt.Sprintf("%s%d", mcpCachePrefix, id)
	core.AppCache.Delete(cacheKey)

	return nil
}

// Update 更新MCP信息
func (srv *McpService) Update(id uint64, mcpDTO dto.McpDTO) error {
	// 开启事务
	tx := core.DB.Begin()

	var mcp model.Mcp
	if err := tx.First(&mcp, id).Error; err != nil {
		tx.Rollback()
		return ErrMcpNotFound
	}

	// 检查名称是否被其他MCP使用
	if mcpDTO.Name != "" && mcpDTO.Name != mcp.Name {
		var existMcp model.Mcp
		if tx.Where("name = ? AND id != ?", mcpDTO.Name, id).First(&existMcp).RowsAffected > 0 {
			tx.Rollback()
			return ErrMcpExists
		}
	}

	// 更新MCP信息
	updates := map[string]interface{}{
		"name":       mcpDTO.Name,
		"describe":   mcpDTO.Describe,
		"type":       mcpDTO.Type,
		"status":     mcpDTO.Status,
		"cmd":        mcpDTO.Cmd,
		"params":     mcpDTO.Params,
		"env":        mcpDTO.Env,
		"updated_at": time.Now(),
	}

	if err := tx.Model(&mcp).Updates(updates).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return err
	}

	// 从缓存删除
	cacheKey := fmt.Sprintf("%s%d", mcpCachePrefix, id)
	core.AppCache.Delete(cacheKey)

	return nil
}

// GetById 根据ID获取MCP信息
func (srv *McpService) GetById(id uint64) (*model.Mcp, error) {
	// 尝试从缓存获取
	cacheKey := fmt.Sprintf("%s%d", mcpCachePrefix, id)
	if cacheData, found := core.AppCache.Get(cacheKey); found {
		if mcp, ok := cacheData.(model.Mcp); ok {
			return &mcp, nil
		}
	}

	var mcp model.Mcp
	if err := core.DB.First(&mcp, id).Error; err != nil {
		return nil, ErrMcpNotFound
	}

	// 存入缓存
	core.AppCache.Set(cacheKey, mcp, 10*time.Minute)

	return &mcp, nil
}

// GetPage 分页获取MCP列表
func (srv *McpService) GetPage(pageRequest paginate.PageRequest) (*paginate.PageResponse, error) {

	pageResult, err := srv.mcpRepository.GetUserPage(pageRequest)
	if err != nil {
		return nil, ErrDatabaseError
	}
	return pageResult, nil
}

// GetTools 获取所有可用工具
func (srv *McpService) GetTools() ([]model.Mcp, error) {
	return srv.mcpRepository.GetTools()
}
